package com.kuang.exam.modules.paper.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kuang.exam.core.api.dto.PagingReqDTO;
import com.kuang.exam.core.exception.ServiceException;
import com.kuang.exam.core.utils.BeanMapper;
import com.kuang.exam.core.utils.DateUtils;
import com.kuang.exam.core.utils.StringUtils;
import com.kuang.exam.modules.enums.JoinType;
import com.kuang.exam.modules.exam.dto.ExamDTO;
import com.kuang.exam.modules.exam.dto.ExamRepoDTO;
import com.kuang.exam.modules.exam.service.ExamRepoService;
import com.kuang.exam.modules.exam.service.ExamService;
import com.kuang.exam.modules.paper.dto.PaperQuDTO;
import com.kuang.exam.modules.paper.dto.export.PaperExportDTO;
import com.kuang.exam.modules.paper.dto.ext.PaperQuAnswerExtDTO;
import com.kuang.exam.modules.paper.dto.ext.PaperQuDetailDTO;
import com.kuang.exam.modules.paper.dto.request.PaperAnswerDTO;
import com.kuang.exam.modules.paper.dto.request.PaperListReqDTO;
import com.kuang.exam.modules.paper.dto.response.ExamDetailRespDTO;
import com.kuang.exam.modules.paper.dto.response.ExamResultRespDTO;
import com.kuang.exam.modules.paper.dto.response.PaperListRespDTO;
import com.kuang.exam.modules.paper.entity.Paper;
import com.kuang.exam.modules.paper.entity.PaperQu;
import com.kuang.exam.modules.paper.entity.PaperQuAnswer;
import com.kuang.exam.modules.paper.enums.ExamState;
import com.kuang.exam.modules.paper.enums.PaperState;
import com.kuang.exam.modules.paper.mapper.PaperMapper;
import com.kuang.exam.modules.paper.service.PaperQuAnswerService;
import com.kuang.exam.modules.paper.service.PaperQuService;
import com.kuang.exam.modules.paper.service.PaperService;
import com.kuang.exam.modules.qu.dto.QuAnswerDTO;
import com.kuang.exam.modules.qu.entity.Qu;
import com.kuang.exam.modules.qu.entity.QuAnswer;
import com.kuang.exam.modules.qu.enums.QuType;
import com.kuang.exam.modules.qu.service.QuAnswerService;
import com.kuang.exam.modules.qu.service.QuService;
import com.kuang.exam.modules.sys.depart.entity.SysDepart;
import com.kuang.exam.modules.sys.depart.service.SysDepartService;
import com.kuang.exam.modules.sys.user.entity.SysUser;
import com.kuang.exam.modules.sys.user.service.SysUserService;
import com.kuang.exam.modules.user.book.service.UserBookService;
import com.kuang.exam.modules.user.exam.service.UserExamService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * <p>
 * 语言设置 服务实现类
 * </p>
 */
@Service
public class PaperServiceImpl extends ServiceImpl<PaperMapper, Paper> implements PaperService {


    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private ExamService examService;

    @Autowired
    private QuService quService;

    @Autowired
    private QuAnswerService quAnswerService;

    @Autowired
    private PaperService paperService;

    @Autowired
    private PaperQuService paperQuService;

    @Autowired
    private PaperQuAnswerService paperQuAnswerService;

    @Autowired
    private UserBookService userBookService;

    @Autowired
    private ExamRepoService examRepoService;

    @Autowired
    private UserExamService userExamService;

    @Autowired
    private SysDepartService departService;

    /**
     * 展示的选项，ABC这样
     */
    private static List<String> ABC = Arrays.asList(new String[]{
            "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X"
            , "Y", "Z"
    });


    @Override
    public String createPaper(String userId, String examId) {

        // 查找考试
        ExamDTO exam = examService.findById(examId);

        if (exam == null) {
            throw new ServiceException(1, "考试不存在！");
        }

        if (!ExamState.ENABLE.equals(exam.getState())) {
            throw new ServiceException(1, "考试状态不正确！");
        }

        // 考试题目列表
        List<PaperQu> quList = new ArrayList<>();

        // 按题库组卷的
        if (JoinType.REPO_JOIN.equals(exam.getJoinType())) {
            //查找规则选定的题库
            quList = this.generateByRepo(examId, exam.getLevel());
        }

        if (CollectionUtils.isEmpty(quList)) {
            throw new ServiceException(1, "规则不正确，无对应的考题！");
        }

        //保存试卷内容
        String paperId = this.savePaper(userId, exam, quList);

        return paperId;
    }

    @Override
    public ExamDetailRespDTO paperDetail(String paperId) {


        ExamDetailRespDTO respDTO = new ExamDetailRespDTO();

        // 试题基本信息
        Paper paper = paperService.getById(paperId);
        BeanMapper.copy(paper, respDTO);

        // 查找题目列表
        List<PaperQuDTO> list = paperQuService.listByPaper(paperId);

        List<PaperQuDTO> radioList = new ArrayList<>();
        List<PaperQuDTO> multiList = new ArrayList<>();
        List<PaperQuDTO> judgeList = new ArrayList<>();
        List<PaperQuDTO> fillList = new ArrayList<>();
        List<PaperQuDTO> subjectList = new ArrayList<>();
        for (PaperQuDTO item : list) {
            if (QuType.RADIO.equals(item.getQuType())) {
                radioList.add(item);
            } else if (QuType.MULTI.equals(item.getQuType())) {
                multiList.add(item);
            } else if (QuType.JUDGE.equals(item.getQuType())) {
                judgeList.add(item);
            } else if (QuType.FILL.equals(item.getQuType())) {
                fillList.add(item);
            } else if (QuType.SUBJECT.equals(item.getQuType())) {
                subjectList.add(item);
            }
        }

        respDTO.setRadioList(radioList);
        respDTO.setMultiList(multiList);
        respDTO.setJudgeList(judgeList);
        respDTO.setFillList(fillList);
        respDTO.setSubjectList(subjectList);

        return respDTO;
    }

    @Override
    public ExamResultRespDTO paperResult(String paperId) {

        ExamResultRespDTO respDTO = new ExamResultRespDTO();

        //根据id查试卷
        Paper paper = paperService.getById(paperId);
        BeanMapper.copy(paper, respDTO);

        List<PaperQuDetailDTO> quList = paperQuService.listForPaperResult(paperId);
        respDTO.setQuList(quList);

        return respDTO;
    }

    @Override
    public PaperQuDetailDTO findQuDetail(String paperId, String quId) {

        PaperQuDetailDTO respDTO = new PaperQuDetailDTO();
        // 问题
        Qu qu = quService.getById(quId);

        // 基本信息
        PaperQu paperQu = paperQuService.findByKey(paperId, quId);
        BeanMapper.copy(paperQu, respDTO);
        respDTO.setContent(qu.getContent());

        // 答案列表,除主观题外
        if (!paperQu.getQuType().equals(QuType.SUBJECT)) {
            List<PaperQuAnswerExtDTO> list = paperQuAnswerService.listForExam(paperId, quId);
            if (paperQu.getQuType().equals(QuType.FILL) && list != null) { //填空题,注意清空答案
                list.forEach(paperQuAnswerExtDTO -> paperQuAnswerExtDTO.setContent(""));
            }
            respDTO.setAnswerList(list);

        }

        return respDTO;
    }


    /**
     * 题库组题方式产生题目列表
     *
     * @param examId
     * @return
     */
    private List<PaperQu> generateByRepo(String examId, Integer level) {

        // 查找规则指定的题库
        List<ExamRepoDTO> list = examRepoService.listByExam(examId);

        //最终的题目列表
        List<PaperQu> quList = new ArrayList<>();

        //排除ID，避免题目重复
        List<String> excludes = new ArrayList<>();
        excludes.add("none");

        if (!CollectionUtils.isEmpty(list)) {
            for (ExamRepoDTO item : list) {

                // 单选题
                if (item.getRadioCount() > 0) {
                    List<Qu> radioList = quService.listByRandom(item.getRepoId(), QuType.RADIO, level, excludes, item.getRadioCount());
                    for (Qu qu : radioList) {
                        PaperQu paperQu = this.processPaperQu(item, qu);
                        quList.add(paperQu);
                        excludes.add(qu.getId());
                    }
                }

                //多选题
                if (item.getMultiCount() > 0) {
                    List<Qu> multiList = quService.listByRandom(item.getRepoId(), QuType.MULTI, level, excludes, item.getMultiCount());
                    for (Qu qu : multiList) {
                        PaperQu paperQu = this.processPaperQu(item, qu);
                        quList.add(paperQu);
                        excludes.add(qu.getId());
                    }
                }

                // 判断题
                if (item.getJudgeCount() > 0) {
                    List<Qu> judgeList = quService.listByRandom(item.getRepoId(), QuType.JUDGE, level, excludes, item.getJudgeCount());
                    for (Qu qu : judgeList) {
                        PaperQu paperQu = this.processPaperQu(item, qu);
                        quList.add(paperQu);
                        excludes.add(qu.getId());
                    }
                }

                // 填空题
                if (item.getFillCount() > 0) {
                    List<Qu> fillList = quService.listByRandom(item.getRepoId(), QuType.FILL, level, excludes, item.getFillCount());
                    for (Qu qu : fillList) {
                        PaperQu paperQu = this.processPaperQu(item, qu);
                        quList.add(paperQu);
                        excludes.add(qu.getId());
                    }
                }

                // 主观题
                if (item.getSubjectCount() > 0) {
                    List<Qu> subjectList = quService.listByRandom(item.getRepoId(), QuType.SUBJECT, level, excludes, item.getSubjectCount());
                    for (Qu qu : subjectList) {
                        PaperQu paperQu = this.processPaperQu(item, qu);
                        quList.add(paperQu);
                        excludes.add(qu.getId());
                    }
                }
            }
        }
        return quList;
    }


    /**
     * 填充试题题目信息
     *
     * @param repo
     * @param qu
     * @return
     */
    private PaperQu processPaperQu(ExamRepoDTO repo, Qu qu) {

        //保存试题信息
        PaperQu paperQu = new PaperQu();
        paperQu.setQuId(qu.getId());
        paperQu.setAnswered(false);
        paperQu.setIsRight(false);
        paperQu.setQuType(qu.getQuType());

        if (QuType.RADIO.equals(qu.getQuType())) {
            paperQu.setScore(repo.getRadioScore());
//            paperQu.setActualScore(repo.getRadioScore());
        } else if (QuType.MULTI.equals(qu.getQuType())) {
            paperQu.setScore(repo.getMultiScore());
//            paperQu.setActualScore(repo.getMultiScore());
        } else if (QuType.JUDGE.equals(qu.getQuType())) {
            paperQu.setScore(repo.getJudgeScore());
//            paperQu.setActualScore(repo.getJudgeScore());
        } else if (QuType.FILL.equals(qu.getQuType())) {
            paperQu.setScore(repo.getFillScore());
//            paperQu.setActualScore(repo.getFillScore());
        } else if (QuType.SUBJECT.equals(qu.getQuType())) {
            paperQu.setScore(repo.getSubjectScore());
//            paperQu.setActualScore(repo.getSubjectScore());
        }

        return paperQu;
    }


    /**
     * 保存试卷
     *
     * @param userId
     * @param exam
     * @param quList
     * @return
     */
    private String savePaper(String userId, ExamDTO exam, List<PaperQu> quList) {

        // 查找用户
        SysUser user = sysUserService.getById(userId);

        //保存试卷基本信息
        Paper paper = new Paper();
        paper.setId(IdWorker.getIdStr());
        paper.setTeacherId(exam.getTeacherId());
        paper.setDepartId(user.getDepartId());
        paper.setExamId(exam.getId());
        paper.setTitle(exam.getTitle());
        paper.setTotalScore(exam.getTotalScore());
        paper.setTotalTime(exam.getTotalTime());
        paper.setUserScore(0);
        paper.setUserId(userId);
        paper.setCreateTime(new Date());
        paper.setUpdateTime(new Date());
        paper.setQualifyScore(exam.getQualifyScore());
        paper.setState(PaperState.ING);

        // 截止时间
        Calendar cl = Calendar.getInstance();
        cl.setTimeInMillis(System.currentTimeMillis());
        cl.add(Calendar.MINUTE, exam.getTotalTime());
        paper.setLimitTime(cl.getTime());


        boolean hasSub = false;
        if (!CollectionUtils.isEmpty(quList)) {
            //保存试卷题目信息,并返回题目中是否存在主观题
            hasSub = this.savePaperQu(paper.getId(), quList);
        }
        paper.setHasSaq(hasSub);
        //保存试卷信息
        paperService.save(paper);
        return paper.getId();
    }


    /**
     * 保存试卷试题列表
     *
     * @param paperId
     * @param quList
     * @return 返回题目中是否存在主观题
     */
    private boolean savePaperQu(String paperId, List<PaperQu> quList) {

        boolean hasSub = false;

        List<PaperQu> batchQuList = new ArrayList<>();
        List<PaperQuAnswer> batchAnswerList = new ArrayList<>();

        int sort = 0;
        for (PaperQu item : quList) {

            item.setPaperId(paperId);
            item.setSort(sort);
            item.setId(IdWorker.getIdStr());

            if (item.getQuType().equals(QuType.SUBJECT)) {
                hasSub = true;
            } else { //非主观题
                // 回答列表
                List<QuAnswer> answerList = quAnswerService.listAnswerByRandom(item.getQuId());

                if (!CollectionUtils.isEmpty(answerList)) {

                    int i = 0;
                    for (QuAnswer answer : answerList) {
                        PaperQuAnswer paperQuAnswer = new PaperQuAnswer();
                        paperQuAnswer.setId(UUID.randomUUID().toString());
                        paperQuAnswer.setPaperId(paperId);
                        paperQuAnswer.setQuId(answer.getQuId());
                        paperQuAnswer.setAnswerId(answer.getId());
                        paperQuAnswer.setChecked(false);
                        paperQuAnswer.setSort(i);
                        paperQuAnswer.setAbc(ABC.get(i));
                        paperQuAnswer.setIsRight(answer.getIsRight());
                        i++;
                        batchAnswerList.add(paperQuAnswer);
                    }
                }
            }
            batchQuList.add(item);
            sort++;
        }

        //添加问题
        paperQuService.saveBatch(batchQuList);
        //批量添加问题答案
        paperQuAnswerService.saveBatch(batchAnswerList);

        return hasSub;
    }

    @Override
    public void fillAnswer(PaperAnswerDTO reqDTO) {

        // 未作答
        if (CollectionUtils.isEmpty(reqDTO.getAnswers()) && StringUtils.isBlank(reqDTO.getAnswer())) {
            return;
        }

        PaperQu quOrigin = paperQuService.findByKey(reqDTO.getPaperId(), reqDTO.getQuId());

        //查找答案列表
        List<PaperQuAnswer> list = paperQuAnswerService.listForFill(reqDTO.getPaperId(), reqDTO.getQuId());

        //是否正确
        boolean right = true;

        //更新正确答案
        for (PaperQuAnswer item : list) {
            //更新是否选中
            if (reqDTO.getAnswers().contains(item.getId())) {
                item.setChecked(true);
            } else {
                item.setChecked(false);
            }

            //有一个对不上就是错的
            if (item.getIsRight() != null && !item.getIsRight().equals(item.getChecked())) {
                right = false;
            }
            paperQuAnswerService.updateById(item);
        }

        //修改为已回答
        PaperQu qu = new PaperQu();
        qu.setQuId(reqDTO.getQuId());
        qu.setPaperId(reqDTO.getPaperId());
        qu.setIsRight(right);
        qu.setAnswer(reqDTO.getAnswer());       // 填空题，主观题答案
        qu.setAnswered(true);
        if (QuType.FILL.equals(quOrigin.getQuType())) {  // 填空题
            int actualScore = calcOneFillScore(reqDTO.getPaperId(), reqDTO.getQuId(), reqDTO.getAnswers());
            qu.setActualScore(actualScore);
            qu.setIsRight(actualScore == quOrigin.getScore());      //实际得分和单题总分一致则说明对了
        } else if (QuType.SUBJECT.equals(quOrigin.getQuType())) { //主观题
            qu.setActualScore(0);
        } else {
            qu.setActualScore(right ? quOrigin.getScore() : 0);
        }

        paperQuService.updateByKey(qu);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void handExam(String paperId) {

        //获取试卷信息
        Paper paper = paperService.getById(paperId);

        //如果不是正常的，抛出异常
        if (!PaperState.ING.equals(paper.getState())) {
            throw new ServiceException(1, "试卷状态不正确！");
        }

        // 客观分：
        int objScore = paperQuService.sumObjective(paperId);
        paper.setObjScore(objScore);
        paper.setUserScore(objScore);

        // 主观分，因为要阅卷，所以给0
        paper.setSubjScore(0);

        // 待阅卷
        if (paper.getHasSaq()) {
            paper.setState(PaperState.WAIT_OPT);
        } else {

            // 同步保存考试成绩
            userExamService.joinResult(paper.getUserId(), paper.getExamId(), objScore, objScore >= paper.getQualifyScore());

            paper.setState(PaperState.FINISHED);
        }
        paper.setUpdateTime(new Date());

        //计算考试时长
        Calendar cl = Calendar.getInstance();
        cl.setTimeInMillis(System.currentTimeMillis());
        int userTime = (int) ((System.currentTimeMillis() - paper.getCreateTime().getTime()) / 1000 / 60);
        if (userTime == 0) {
            userTime = 1;
        }
        paper.setUserTime(userTime);

        //更新试卷
        paperService.updateById(paper);

        //把答错的问题加入错题本
        List<PaperQuDTO> list = paperQuService.listByPaper(paperId);
        for (PaperQuDTO qu : list) {
            // 主观题和对的都不加入错题库
            if (qu.getIsRight()) {
                continue;
            }
            //加入错题本
            userBookService.addBook(paper.getExamId(), qu.getQuId());
        }
    }

    /**
     * 计算整张试卷填空题的分数
     *
     * @param paperId
     * @return
     */
    private int calcFillScore(String paperId) {
        // 1、找出所有填空题
        QueryWrapper<PaperQu> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(PaperQu::getPaperId, paperId)
                .eq(PaperQu::getQuType, QuType.FILL);
        List<PaperQu> fillList = paperQuService.list(wrapper);
        // 2、计算分值
        int result = 0;
        for (PaperQu paperQu : fillList) {
            String quId = paperQu.getQuId();
            // 查找用户答案
            String[] userAnswers = paperQu.getAnswer().split(",");
            // 查找标准答案
            List<QuAnswerDTO> quAnswerDTOS = quAnswerService.listByQu(quId);
            List<String> quAnswers = new ArrayList<>(quAnswerDTOS.size());
            quAnswerDTOS.forEach(quAnswerDTO -> quAnswers.add(quAnswerDTO.getContent()));
            // 单个空的分值
            int oneScore = (int) Math.ceil((double) paperQu.getScore() / quAnswers.size());
            int rightNum = 0; // 正确的个数
            for (String userAnswer : userAnswers) {
                if (quAnswers.contains(userAnswer)) {
                    rightNum++;
                }
            }
            result += oneScore * rightNum >= paperQu.getScore() ? paperQu.getScore() : oneScore * rightNum;
        }
        return result;
    }

    /**
     * 计算单道填空题的分值
     *
     * @param paperId
     * @param quId
     * @param userAnswers
     * @return
     */
    private int calcOneFillScore(String paperId, String quId, List<String> userAnswers) {
        PaperQu paperQu = paperQuService.findByKey(paperId, quId);
        // 查找标准答案
        List<QuAnswerDTO> quAnswerDTOS = quAnswerService.listByQu(quId);
        List<String> quAnswers = new ArrayList<>(quAnswerDTOS.size());
        quAnswerDTOS.forEach(quAnswerDTO -> quAnswers.add(quAnswerDTO.getContent()));
        // 单个空的分值
        int oneScore = (int) Math.ceil((double) paperQu.getScore() / quAnswers.size());
        int rightNum = 0; // 正确的个数
        for (String userAnswer : userAnswers) {
            if (quAnswers.contains(userAnswer)) {
                rightNum++;
            }
        }
        return oneScore * rightNum >= paperQu.getScore() ? paperQu.getScore() : oneScore * rightNum;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void reviewPaper(ExamResultRespDTO reqDTO) {

        List<PaperQuDetailDTO> quList = reqDTO.getQuList();
        List<PaperQu> list = new ArrayList<>();
        for (PaperQuDetailDTO item : quList) {
            if (item.getQuType().equals(QuType.SUBJECT)) {
                PaperQu qu = new PaperQu();
                qu.setId(item.getId());
                qu.setActualScore(item.getActualScore());
                list.add(qu);
            }
        }

        // 批量修改
        paperQuService.updateBatchById(list);

        // 主观分
        int subjScore = paperQuService.sumSubjective(reqDTO.getId());

        // 修改试卷状态
        Paper paper = this.getById(reqDTO.getId());
        paper.setSubjScore(subjScore);
        paper.setUserScore(paper.getObjScore() + subjScore);
        paper.setState(PaperState.FINISHED);
        paper.setUpdateTime(new Date());
        this.updateById(paper);

        // 同步保存考试成绩
        userExamService.joinResult(paper.getUserId(), paper.getExamId(), paper.getUserScore(), paper.getUserScore() >= paper.getQualifyScore());
    }

    @Override
    public IPage<PaperListRespDTO> paging(PagingReqDTO<PaperListReqDTO> reqDTO) {
        List<String> subIds = new ArrayList<>();
        if (reqDTO.getParams() != null && !StringUtils.isBlank(reqDTO.getParams().getDepartId())) {
            subIds = departService.listAllSubIds(reqDTO.getParams().getDepartId());
            reqDTO.getParams().setDepartIds(subIds);
        }
        return baseMapper.paging(reqDTO.toPage(), reqDTO.getParams());
    }

    @Override
    public boolean isExist(String userId, String examId) {
        QueryWrapper<Paper> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(Paper::getUserId, userId)
                .eq(Paper::getExamId, examId);
        int count = this.count(wrapper);
        return count > 0;
    }

    @Override
    public List<Paper> listByExamId(String examId) {
        QueryWrapper<Paper> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(Paper::getExamId, examId);
        return this.list(wrapper);
    }

    @Override
    public Integer calcPaperNum(String examId) {
        QueryWrapper<Paper> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(Paper::getExamId, examId);
        return this.count(wrapper);
    }

    @Override
    public Integer calcReviewPaperNum(String examId) {
        QueryWrapper<Paper> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(Paper::getExamId, examId)
                .eq(Paper::getState, PaperState.WAIT_OPT);
        return this.count(wrapper);
    }

    @Override
    public Integer calcNoReviewPaperNum(String examId) {
        QueryWrapper<Paper> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .eq(Paper::getExamId, examId)
                .eq(Paper::getState, PaperState.FINISHED);
        return this.count(wrapper);
    }

    @Override
    public List<PaperExportDTO> listForExport(PaperListReqDTO reqDTO) {
        //1.查询指定条件下的所有试卷
        List<String> subIds = new ArrayList<>();
        if (reqDTO != null && !StringUtils.isBlank(reqDTO.getDepartId())) {
            subIds = departService.listAllSubIds(reqDTO.getDepartId());
            reqDTO.setDepartIds(subIds);
        }
        List<PaperListRespDTO> papers = baseMapper.listForExport(reqDTO);

        //2.封装导出数据
        List<PaperExportDTO> result = new ArrayList<>();
        papers.forEach(paper -> {
            PaperExportDTO exportDTO = new PaperExportDTO();
            exportDTO.setTitle(paper.getTitle());
            exportDTO.setCreateTime(DateUtils.formatDate(paper.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
            exportDTO.setUserTime(paper.getUserTime() + "/" + paper.getTotalTime());
            SysDepart depart = departService.getById(paper.getDepartId());
            exportDTO.setDepartName(depart == null ? "" : depart.getDeptName());
            SysUser user = sysUserService.getById(paper.getUserId());
            exportDTO.setUserName(user == null ? "" : user.getRealName());
            exportDTO.setObjScore(paper.getObjScore().toString());
            exportDTO.setSubjScore(paper.getSubjScore().toString());
            exportDTO.setUserScore(paper.getUserScore() + "/" + paper.getTotalScore());
            exportDTO.setUserResult(paper.getUserScore() >= paper.getQualifyScore() ? "合格" : "不合格");
            result.add(exportDTO);
        });
        return result;
    }

    @Override
    public List<Paper> findDeadPapers() {

        // 结束后两分钟，非正常交卷
        Calendar cl = Calendar.getInstance();
        cl.setTimeInMillis(System.currentTimeMillis());
        cl.add(Calendar.MINUTE, -5);

        QueryWrapper<Paper> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .le(Paper::getLimitTime, cl.getTime())
                .eq(Paper::getState, PaperState.ING);


        return this.list(wrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void breakExam(String paperId) {

        Paper paper = new Paper();
        paper.setId(paperId);
        paper.setState(PaperState.BREAK);
        paper.setUpdateTime(new Date());
        this.updateById(paper);
    }
}
